<?php

declare(strict_types=1);
/**
 * This file is part of MoChat.
 * @link     https://mo.chat
 * @document https://mochat.wiki
 * @contact  group@mo.chat
 * @license  https://github.com/mochat-cloud/mochat/blob/master/LICENSE
 */
namespace MoChat\App\WorkRoom\Action\Workbench;

use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\Middleware;
use Hyperf\HttpServer\Annotation\Middlewares;
use Hyperf\HttpServer\Annotation\RequestMapping;
use MoChat\App\Common\Middleware\WorkbenchAuthMiddleware;
use MoChat\App\User\Contract\UserContract;
use MoChat\App\Utils\Common;
use MoChat\App\WorkContact\Contract\WorkContactRoomContract;
use MoChat\App\WorkEmployee\Contract\WorkEmployeeContract;
use MoChat\App\WorkRoom\Contract\WorkRoomContract;
use MoChat\Framework\Action\AbstractAction;
use MoChat\Framework\Constants\ErrorCode;
use MoChat\Framework\Exception\CommonException;
use MoChat\Framework\Request\ValidateSceneTrait;

/**
 * 拉新统计-客户群统计.
 *
 * Class RoomStatistics.
 * @Controller
 */
class RoomStatistics extends AbstractAction
{
    use ValidateSceneTrait;

    /**
     * @Inject
     * @var WorkRoomContract
     */
    protected $workRoomService;

    /**
     * @Inject
     * @var WorkContactRoomContract
     */
    protected $workContactRoomService;

    /**
     * @Inject
     * @var UserContract
     */
    protected $userService;

    /**
     * @Inject
     * @var WorkEmployeeContract
     */
    protected $workEmployeeService;

    /**
     * @Middlewares({
     *     @Middleware(WorkbenchAuthMiddleware::class)
     * })
     * @RequestMapping(path="/workbench/workRoom/roomStatistics", methods="get")
     * @return array 返回数组
     */
    public function handle(): array
    {
        $user = user();
        // 判断用户绑定企业信息
        if (! isset($user['corpId'])) {
            throw new CommonException(ErrorCode::INVALID_PARAMS, '未选择登录企业，不可操作');
        }
        $params['userId'] = (int) $user['logUserId'];
        $params['corpId'] = $user['corpId'];
        $params['employeeId'] = $user['id'];
        // 接收参数
        $params['day'] = $this->request->input('day');
        // 参数验证
        $this->validated($params);
        // 处理参数
        $params = $this->handleParam($params);

        // 客户群统计
        $statistics = $this->statistics($params);

        // 客户群日统计
        $dayStatistics = $this->dayStatistics($params);

        // 员工排行
        $employeeRanking = $this->employeeRanking($params);
        return ['statistics' => $statistics, 'dayStatistics' => $dayStatistics, 'employeeRanking' => $employeeRanking];
    }

    /**
     * 验证规则.
     *
     * @return array 响应数据
     */
    protected function rules(): array
    {
        return [
            'day' => 'required',
        ];
    }

    /**
     * 验证错误提示.
     * @return array 响应数据
     */
    protected function messages(): array
    {
        return [
            'day.required' => '日期 必传',
        ];
    }

    private function employeeRanking($params): array
    {
        $employeeRanking = [];
        // 所有客户群
        $rooms = $this->workRoomService->getWorkRoomsByCorpId($params['corpId'], ['id', 'owner_id']);
        $roomIds = array_column($rooms, 'id');
        // 所有群昨日新增客户
        $roomContact = $this->workContactRoomService->countWorkContactRoomsByRoomIdsDays($roomIds, [date('y-m-d', strtotime('-1 day')), date('Y-m-d')]);

        $employeeIds = array_unique(array_column($rooms, 'ownerId'));
        $rooms = array_column($rooms, null, 'id');
        // 所有群主
        $employees = $this->workEmployeeService->getWorkEmployeesById($employeeIds, ['id', 'name', 'avatar']);
        $employees = array_column($employees, null, 'id');
        foreach ($roomContact as &$item) {
            $item['ownerId'] = $rooms[$item['roomId']] ? $rooms[$item['roomId']]['ownerId'] : 0;
            if ($item['ownerId'] > 0) {
                $employeeRanking[$item['ownerId']]['id'] = $item['ownerId'];
                $employeeRanking[$item['ownerId']]['name'] = ! empty($employees[$item['ownerId']]) ? $employees[$item['ownerId']]['name'] : '';
                $employeeRanking[$item['ownerId']]['avatar'] = ! empty($employees[$item['ownerId']]) ? file_full_url($employees[$item['ownerId']]['avatar']) : '';
                $employeeRanking[$item['ownerId']]['total'] = ! empty($employeeRanking[$item['ownerId']]['total']) ? $employeeRanking[$item['ownerId']]['total'] + $item['total'] : $item['total'];
            }
        }
        return empty($employeeRanking) ? [] : Common::arraySort($employeeRanking, 'total', 'desc');
    }

    /**
     * 处理参数.
     * @param array $params 接受参数
     * @return array 响应数组
     */
    private function handleParam(array $params): array
    {
        $params['roomIds'] = [];
        // 员工为群主的客户群
        $rooms = $this->workRoomService->getWorkRoomsBySearch(['corpId' => $params['corpId'], 'ownerId' => [$params['employeeId']]], ['id']);
        empty($rooms) || $params['roomIds'] = array_column($rooms, 'id');
        if ($params['userId'] > 0) {
            $userInfo = $this->userService->getUserById($params['userId'], ['is_root']);
            // 超级管理员查询所有客户群
            if (! empty($userInfo) && $userInfo['isRoot'] === 1) {
                $rooms = $this->workRoomService->getWorkRoomsBySearch(['corpId' => $params['corpId']], ['id']);
                empty($rooms) || $params['roomIds'] = array_column($rooms, 'id');
            }
        }
        return $params;
    }

    private function dayStatistics(array $params): array
    {
        // 新增客户群数
        $addRooms = $this->workRoomService->countWorkRoomByRoomIdsGroupByCreateTime(['corpId' => $params['corpId'], 'roomIds' => $params['roomIds']]);
        empty($addRooms) || $addRooms = array_column($addRooms, null, 'createTime');
        // 新入群客户数
        $addContact = $this->workContactRoomService->countWorkContactRoomsByRoomIdsDayGroupByCreateTime($params['roomIds'], $params['day'], 1, 1);
        empty($addContact) || $addContact = array_column($addContact, null, 'createTime');
        // 新退群客户数
        $lossContact = $this->workContactRoomService->countWorkContactRoomsByRoomIdsDayGroupByCreateTime($params['roomIds'], $params['day'], 2, 2);
        empty($lossContact) || $lossContact = array_column($lossContact, null, 'createTime');
        $day = $params['day'];
        $dayStatistics = [];
        for ($i = 0; $i < 30; ++$i) {
            $dayStatistics[$day]['day'] = $day;
            $dayStatistics[$day]['addRoom'] = isset($addRooms[$day]) ? $addRooms[$day]['total'] : 0;
            $dayStatistics[$day]['addContact'] = isset($addContact[$day]) ? $addContact[$day]['total'] : 0;
            $dayStatistics[$day]['lossContact'] = isset($lossContact[$day]) ? $lossContact[$day]['total'] : 0;
            $day = date('Y-m-d', strtotime($day) + 86400);
            if (strtotime($day) > strtotime(date('Y-m-d'))) {
                break;
            }
        }
        return array_values($dayStatistics);
    }

    private function statistics(array $params): array
    {
        $statistics = ['total' => count($params['roomIds']), 'totalContact' => 0, 'addContact' => 0, 'lossContact' => 0];
        if (! empty($params['roomIds'])) {
            $rooms = $this->workRoomService->getWorkRoomsBySearch(['corpId' => $params['corpId'], 'ownerId' => [$params['employeeId']], 'day' => $params['day']], ['id']);
            // 客户群总数
            $statistics['total'] = count($rooms);
            // 群总人数
            $statistics['totalContact'] = $this->workContactRoomService->countWorkContactRoomByRoomIds($params['roomIds']);
            // 新入群客户数
            $tomorrow = date('Y-m-d', strtotime('+1 day'));
            $statistics['addContact'] = $this->workContactRoomService->countAddWorkContactRoomsByRoomIdTime($params['roomIds'], $params['day'], $tomorrow);
            $statistics['lossContact'] = $this->workContactRoomService->countQuitWorkContactRoomsByRoomIdTime($params['roomIds'], $params['day'], $tomorrow);
        }
        return $statistics;
    }
}
